﻿using System;
using System.Collections;
using System.Data;
using System.Data.Common;
using System.Xml;
using System.IO;
using System.Web.Caching;
using System.Configuration;

namespace IHISCETeim.Library
{
    /// <summary>
    /// 缓存类
    /// 对缓存进行全局控制管理
    /// </summary>
    public class DataCache
    {
        
        private static ICacheStrategy cs;
        private static volatile DataCache instance = null;
        private static object lockHelper = new object();


        /// <summary>
        /// 构造函数
        /// </summary>
        private DataCache()
        {
            try{
                string webcachekey = ConfigurationManager.AppSettings["webcachekey"].ToString().Trim();
                switch (webcachekey) { 
                    case "default":
                        cs = new DefaultCacheStrategy();
                        break;
                    case "file":
                        cs = new FileCacheStrategy();
                        break;
                    case "memcached":
                        cs = new MemcachedCacheStrategy();
                        break;
                    case "cache":
                        cs = new Caching4Strategy();
                        break;
                }
            }
            catch{
                cs = new DefaultCacheStrategy();
            }            
        }

        /// <summary>
        /// 单体模式返回当前类的实例
        /// </summary>
        /// <returns></returns>
        public static DataCache Instance()
        {

            if (instance == null)
            {
                lock (lockHelper)
                {
                    if (instance == null)
                    {
                        instance = new DataCache();
                    }
                }
            }
            return instance;
        }    

        /// <summary>
        /// 添加表类型数据缓存
        /// </summary>
        /// <param name="CacheKey"></param>
        /// <param name="dt"></param>
        public void Add(string CacheKey, DataTable dt)
        {
            lock (lockHelper)
            {
                if (dt.Rows.Count > 0)
                {
                    Add(CacheKey, (object)dt);
                }
            }
        }

        /// <summary>
        /// 添加字符串类型数据缓存
        /// </summary>
        /// <param name="CacheKey"></param>
        /// <param name="str"></param>
        public void Add(string CacheKey, string str)
        {
            lock (lockHelper)
            {
                if (!string.IsNullOrEmpty(str))
                {
                    Add(CacheKey, (object)str);
                }
            }
        }

        /// <summary>
        /// 添加数据行类型数据缓存
        /// </summary>
        /// <param name="CacheKey"></param>
        /// <param name="dr"></param>
        public  void Add(string CacheKey, DataRow dr)
        {
            lock (lockHelper)
            {
                if (dr != null)
                {
                    Add(CacheKey, (object)dr);
                }               
            }
        }

        /// <summary>
        /// 添加int类型数据缓存
        /// </summary>
        /// <param name="CacheKey"></param>
        /// <param name="intvalue"></param>
        public  void Add(string CacheKey, int intvalue)
        {
            lock (lockHelper)
            {
                if (!intvalue.Equals(null))
                {
                    Add(CacheKey, (object)intvalue);
                }                
            }
        }
        
        /// <summary>
        /// 添加字符串数组类型数据缓存
        /// </summary>
        /// <param name="CacheKey"></param>
        /// <param name="strArray"></param>
        public  void Add(string CacheKey, string[] strArray)
        {
            lock (lockHelper)
            {
                if (strArray.Length > 0)
                {
                    Add(CacheKey, (object)strArray);
                }                
            }
        }

        /// <summary>
        /// 缓存CacheKey,加入当前对象信息
        /// </summary>
        /// <param name="CacheKey">缓存KEY</param>
        /// <param name="o">被缓存的对象</param>
        public  void Add(string CacheKey, object o)
        {
            lock (lockHelper)
            {
                //当缓存到期时间为0或负值,则不再放入缓存
                if (cs.TimeOut <= 0) return;
                //向缓存加入新的对象
                cs.Add(CacheKey, o);
            }
        }

        public void Add(string CacheKey, object o, int timeout)
        {
            lock (lockHelper)
            {
                //当缓存到期时间为0或负值,则不再放入缓存
                if (timeout <= 0) return;
                //向缓存加入新的对象
                cs.Add(CacheKey, o,timeout);
            }
        }
        /// <summary>
        /// 取得指定Cache Key下的数据项
        /// </summary>
        /// <param name="CacheKey"></param>
        /// <returns></returns>
        private object RetrieveOriginObject(string CacheKey)
        {
            if (!string.IsNullOrEmpty(CacheKey))
            {
                return cs.Get(CacheKey);
            }
            return null;
        }

        /// <summary>
        /// 取得指定Cache Key下的数据项
        /// </summary>
        /// <param name="CacheKey"></param>
        /// <returns></returns>
        public  object Get(string CacheKey)
        {
            try
            {
                object cacheObject = RetrieveOriginObject(CacheKey);
                return cacheObject;
                //如果有数据时
                if (cacheObject != null)
                {
                    string otype = cacheObject.GetType().Name.ToString();
                    //当缓存类型是数据表类型时
                    if (otype.IndexOf("Table") > 0)
                    {
                        System.Data.DataTable dt = cacheObject as DataTable;
                        if ((dt == null) || (dt.Rows.Count == 0))
                        {
                            return null;
                        }
                        else
                        {
                            return cacheObject;
                        }
                    }

                    //当缓存类型是数组对象时
                    if (otype.IndexOf("[]") > 0)
                    {
                        if (((Array)cacheObject).Length == 0)
                        {
                            return null;
                        }
                        else
                        {
                            return cacheObject;
                        }
                    }

                    //当缓存类型是字符串类型时
                    if (otype == "String")
                    {
                        if (cacheObject.ToString() == "")
                        {
                            return null;
                        }
                        else
                        {
                            return cacheObject;
                        }
                    }

                    //当缓存类型是数据行
                    if (otype.IndexOf("Row") >= 0)
                    {
                        if (cacheObject == null)
                        {
                            return null;
                        }
                        else
                        {
                            return cacheObject;
                        }
                    }

                    //当缓存类型是int
                    if (otype.IndexOf("Int") >= 0)
                    {
                        if (((int)cacheObject).Equals(null))
                        {
                            return null;
                        }
                        else
                        {
                            return cacheObject;
                        }
                    }                    
                }

                return cacheObject;
            }
            catch
            {
                return null;
            }
        }
        /// <summary>
        /// 取得指定Cache Key下的数据项
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="CacheKey"></param>
        /// <returns></returns>
        public T Get<T>(string CacheKey) { 
            return (T)Get(CacheKey); 
        }
        /// <summary>
        /// 获取指定缓存键值的数据,如果为空则使用委托进行回调取数据
        /// </summary>
        /// <param name="cacheItemArgs"></param>
        /// <param name="cacheItemExpired"></param>
        /// <returns></returns>
        public object Get(CacheItemArgs cacheItemArgs, CacheItemExpiredCallback cacheItemExpired)
        {
            Object objObject = Get(cacheItemArgs.CacheKey);

            if (objObject == null) {
                try
                {
                    objObject = cacheItemExpired(cacheItemArgs);
                }
                catch
                {
                    objObject = null;
                }
                if (objObject != null)
                {
                    if (cacheItemArgs.CacheTimeOut <= 0)
                        cacheItemArgs.CacheTimeOut = cs.TimeOut;
                    Add(cacheItemArgs.CacheKey,objObject,cacheItemArgs.CacheTimeOut);
                }
            }

            if (objObject == null)
                return null;
            else
                return objObject;

        }
        /// <summary>
        ///  获取指定缓存键值的数据,如果为空则使用委托进行回调取数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cacheItemArgs"></param>
        /// <param name="cacheItemExpired"></param>
        /// <returns></returns>
        public T Get<T>(CacheItemArgs cacheItemArgs, CacheItemExpiredCallback cacheItemExpired)
        {
            return (T)Get(cacheItemArgs, cacheItemExpired);
        }
        /// <summary>
        /// 通过指定Cache Key删除缓存中的对象
        /// </summary>
        /// <param name="CacheKey">Cache Key</param>
        public  void Remove(string CacheKey)
        {
            lock (lockHelper)
            {
                try
                {
                    cs.Remove(CacheKey);
                }
                catch
                {
                    //如出错误表明当前Cache不存在
                }
            }
        }      


        public void LoadCacheStrategy(ICacheStrategy ics)
        {
            lock (lockHelper)
            {
                cs = ics;
            }
        }


        public void LoadDefaultCacheStrategy()
        {
            lock (lockHelper)
            {
                cs = new DefaultCacheStrategy();
            }
        }

        public bool Clear()
        {
            lock (lockHelper)
            {
                return cs.Clear();
            }
        }
    }
}
